package com.millstein.tsinglog.advice;

import com.google.common.collect.ImmutableMap;
import com.millstein.tsinglog.exception.TsinglogException;
import com.millstein.tsinglog.model.vo.result.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.millstein.tsinglog.commons.enums.ResultCode;

/**
 * shiro相关异常处理类
 */
@RestControllerAdvice
@Slf4j
public class ServerExceptionHandler {

	// 使用EXCEPTIONS存放异常类型和错误代码的映射
	protected static ImmutableMap<Class<? extends Throwable>, ResultCode> EXCEPTIONS;

	//使用builder来构建一个异常类型和错误代码的异常
	protected static ImmutableMap.Builder<Class<? extends Throwable>, ResultCode> builder = ImmutableMap.builder();

	// 构建EXCEPTIONS的信息
	static {
		builder.put(HttpMessageNotReadableException.class, ResultCode.PARAM_TYPE_BIND_ERROR);
		builder.put(org.springframework.web.multipart.MaxUploadSizeExceededException.class, ResultCode.FILE_TOO_BIG);
		builder.put(org.springframework.web.bind.MethodArgumentNotValidException.class, ResultCode.CONTENT_VALID_FAILURE);
		builder.put(org.apache.shiro.authc.UnknownAccountException.class, ResultCode.INCORRECT_USERNAME_OR_PASSWORD);
		builder.put(org.apache.shiro.authc.IncorrectCredentialsException.class, ResultCode.INCORRECT_USERNAME_OR_PASSWORD);
		builder.put(org.apache.shiro.authc.LockedAccountException.class, ResultCode.TOO_MANY_RETRY_FOR_PASSWORD);
		builder.put(org.apache.shiro.authc.DisabledAccountException.class, ResultCode.ACCOUNT_HAS_BEEN_LOCKED);
		builder.put(org.apache.shiro.authz.UnauthorizedException.class, ResultCode.DO_NOT_HAVE_THIS_PERMISSION);
	}

	// 处理自定义异常
	@ExceptionHandler(TsinglogException.class)
	public CommonResult dealWithTsinglogException(TsinglogException e) {
		log.error("发生异常：{}", e.getMessage(), e);
		return CommonResult.failure(e.getResultCode());
	}

	// 处理其他异常
	@ExceptionHandler(Exception.class)
	public CommonResult dealWithOtherException(Exception e) {
		log.error("发生异常：{}", e.getMessage(), e);
		if (EXCEPTIONS == null) {
			EXCEPTIONS = builder.build();
		}
		final ResultCode result = EXCEPTIONS.get(e.getClass());
		if (result != null) {
			return CommonResult.failure(result);
		} else {
			return CommonResult.failure(ResultCode.SERVER_OCCURS_ERROR);
		}
	}

}
